package com.hulk.redis.core;

import java.util.Map;
import java.util.Random;
import java.util.Set;

import javax.annotation.Resource;

import org.springframework.data.redis.connection.jedis.JedisConnection;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;

import redis.clients.jedis.Jedis;

/**
 * 
 * {封装redis 缓存服务器服务接口}
 * 
 * @author Liuxingwen
 * @created 2016年9月19日 下午8:26:01
 * @lastModified
 * @history
 */
@Component("redisHelper")
//@Repository("redisHelper")
public class RedisHelper {
	public static final String LOCKED = "TRUE";
	/** 毫秒与毫微秒的换算单位 1毫秒 = 1000000毫微秒 */
	public static final long MILLI_NANO_CONVERSION = 1000 * 1000L;
	/** 默认超时时间（毫秒） */
	public static final long DEFAULT_TIME_OUT = 1000;
	public static final Random RANDOM = new Random();
	/** 锁的超时时间（秒），过期删除 */
	public static final int EXPIRE = 3 * 60;
	// 锁状态标志
	private boolean locked = false;
	// 操作redis客户端
	private static Jedis jedis;
	// redis连接
	private JedisConnection jedisConnection;

	// @Autowired
	// @Qualifier("jedisConnectionFactory")
	@Resource
	private JedisConnectionFactory jedisConnectionFactory;

	/**
	 * 获取一个jedis 客户端
	 * 
	 * @return
	 */
	private Jedis getJedis() {
		if (jedis == null) {
			// 使用连接池，用完后需要jedisConnection.close();
			jedisConnection = jedisConnectionFactory.getConnection();
			jedis = jedisConnection.getNativeConnection();
			return jedis;

			// System.out.println(jedisConnectionFactory.getConnection().getClientList().size());
			// 未使用连接池
			// return jedisConnectionFactory.getShardInfo().createResource();

		}
		// System.out.println("连接数：" + jedisConnection.getClientList().size());

		return jedis;
	}

	public RedisHelper() {

	}

	/**
	 * 通过key删除（字节）
	 * 
	 * @param key
	 */
	public void del(byte[] key) {
		this.getJedis().del(key);
	}

	/**
	 * 通过key删除
	 * 
	 * @param key
	 */
	public void del(String key) {
		this.getJedis().del(key);
	}

	/**
	 * 添加key value 并且设置存活时间(byte)
	 * 
	 * @param key
	 * @param value
	 * @param liveTime
	 */
	public void set(byte[] key, byte[] value, int liveTime) {
		this.set(key, value);
		this.getJedis().expire(key, liveTime);
	}

	/**
	 * 添加key value 并且设置存活时间
	 * 
	 * @param key
	 * @param value
	 * @param liveTime
	 */
	public void set(String key, String value, int liveTime) {
		this.set(key, value);
		this.getJedis().expire(key, liveTime);
	}

	/**
	 * 添加key value
	 * 
	 * @param key
	 * @param value
	 */
	public void set(String key, String value) {
		this.getJedis().set(key, value);
//		this.getJedis().append(key, value);
	}
	public void set(String key, Map<String, String> value) {
		this.getJedis().hmset(key,  value);
//		this.getJedis().append(key, value);
	}

	/**
	 * 
	 *  ｛删除｝
	 *  @param key
	 *  @author Liuxingwen
	 *  @created 2016年9月20日 上午8:16:13
	 *  @lastModified       
	 *  @history
	 */
	public void delete(String key) {
		this.getJedis().del(key);
	}
	/**
	 * 
	 *  ｛说明该函数的含义和作用，如果函数较为复杂，请详细说明｝
	 *  @param oldkey
	 *  @param newkey
	 *  @author Liuxingwen
	 *  @created 2016年9月20日 上午8:17:19
	 *  @lastModified       
	 *  @history
	 */
	public void rename(String oldkey,String newkey) {
		this.getJedis().rename(oldkey, newkey);
	}
	/**
	 * 添加key value (字节)(序列化)
	 * 
	 * @param key
	 * @param value
	 */
	public void set(byte[] key, byte[] value) {
		this.getJedis().set(key, value);
	}

	/**
	 * 获取redis value (String)
	 * 
	 * @param key
	 * @return
	 */
	public String get(String key) {
		String value = this.getJedis().get(key);
		return value;
	}

	/**
	 * 获取redis value (byte [] )(反序列化)
	 * 
	 * @param key
	 * @return
	 */
	public byte[] get(byte[] key) {
		return this.getJedis().get(key);
	}

	/**
	 * 通过正则匹配keys
	 * 
	 * @param pattern
	 * @return
	 */
	public Set<String> keys(String pattern) {
		return this.getJedis().keys(pattern);
	}

	/**
	 * 检查key是否已经存在
	 * 
	 * @param key
	 * @return
	 */
	public boolean exists(String key) {
		return this.getJedis().exists(key);
	}

	/**
	 * 清空redis 所有数据
	 * 
	 * @return
	 */
	public String flushDB() {
		return this.getJedis().flushDB();
	}

	/**
	 * 查看redis里有多少数据
	 */
	public long dbSize() {
		return this.getJedis().dbSize();
	}

	/**
	 * 检查是否连接成功
	 * 
	 * @return
	 */
	public String ping() {
		return this.getJedis().ping();
	}

	/**
	 * 加锁 应该以： lock(); try { doSomething(); } finally { unlock()； } 的方式调用
	 * 
	 * @param timeout
	 *            超时时间
	 * @return 成功或失败标志
	 */
	public boolean lock(String key, long timeout) {
		long nano = System.nanoTime();
		timeout *= MILLI_NANO_CONVERSION;
		try {
			while ((System.nanoTime() - nano) < timeout) {
				if (this.getJedis().setnx(key, LOCKED) == 1) {
					this.getJedis().expire(key, EXPIRE);
					this.locked = true;
					return this.locked;
				}
				// 短暂休眠，避免出现活锁
				Thread.sleep(3, RANDOM.nextInt(500));
			}
		} catch (Exception e) {
			throw new RuntimeException("Locking error", e);
		}
		return false;
	}

	/**
	 * 加锁 应该以： lock(); try { doSomething(); } finally { unlock()； } 的方式调用
	 * 
	 * @param timeout
	 *            超时时间
	 * @param expire
	 *            锁的超时时间（秒），过期删除
	 * @return 成功或失败标志
	 */
	public boolean lock(String key, long timeout, int expire) {
		long nano = System.nanoTime();
		timeout *= MILLI_NANO_CONVERSION;
		try {
			while ((System.nanoTime() - nano) < timeout) {
				if (this.getJedis().setnx(key, LOCKED) == 1) {
					this.getJedis().expire(key, expire);
					this.locked = true;
					return this.locked;
				}
				// 短暂休眠，避免出现活锁
				Thread.sleep(3, RANDOM.nextInt(500));
			}
		} catch (Exception e) {
			throw new RuntimeException("Locking error", e);
		}
		return false;
	}

	/**
	 * 加锁 应该以： lock(); try { doSomething(); } finally { unlock()； } 的方式调用
	 * 
	 * @return 成功或失败标志
	 */
	public boolean lock(String key) {
		return lock(key, DEFAULT_TIME_OUT);
	}

}